using System;
using System.IO;
using FireStarter.Base;
using FireStarterModeller.BO;
using FireStarterModeller.Logic;
using FireStarterModeller.Test.BO;
using Habanero.BO;
using NUnit.Framework;

namespace FireStarterModeller.Test.Logic
{
    [TestFixture]
    public class TestSolutionCreator
    {
        #region Setup/Teardown

        [TestFixtureSetUp]
        public virtual void TestFixtureSetup()
        {
            TestUtilsLogic.SetupFixture();
        }

        [SetUp]
        public virtual void SetupTest()
        {
            TestUtilsLogic.SetupTest();
        }

        [TearDown]
        public virtual void TearDownTest()
        {
        }

        #endregion

        [Test]
        public void Test_CreateSolution_ShouldCreateStandardTypes()
        {
            //---------------Set up test pack-------------------
            SolutionCreator slnCreator = new SolutionCreator();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            DMSolution solution = slnCreator.CreateSolution();
            //---------------Test Result -----------------------
            Assert.AreEqual(DMSolution.DEFAULT_NEW_SOLUTION_NAME, solution.SolutionName);
            Assert.IsNotNull(solution.DefaultAssembly, "A default assembly should always be created for the Solution");
            AssertPropertyTypesAreCreated(solution);
            AssertGridColumnControlTypesCreated(solution);
            AssertControlTypesCreated(solution);
            AssertFilterControlTypesCreated(solution);
            string message;
            Assert.IsTrue(solution.Status.IsValid(out message), message);
        }

        [Test]
        public void Test_CreateSolution_WithFileName_ShouldSetupSolutionNameCorrectly()
        {
            //---------------Set up test pack-------------------
            SolutionCreator slnCreator = new SolutionCreator();
            string solutionName = TestUtilsShared.GetRandomString();
            string fileName = Path.Combine(Environment.CurrentDirectory, solutionName + ".fstart");
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            DMSolution solution = slnCreator.CreateSolution(fileName);
            //---------------Test Result -----------------------
            Assert.AreEqual(solutionName, solution.SolutionName);
        }

        [Test]
        public void Test_CreateSolution_WithFileName_ShouldSetupDefaultAssembly()
        {
            //---------------Set up test pack-------------------
            SolutionCreator slnCreator = new SolutionCreator();
            string solutionName = TestUtilsShared.GetRandomString();
            string fileName = Path.Combine(Environment.CurrentDirectory, solutionName + ".fstart");
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            DMSolution solution = slnCreator.CreateSolution(fileName);
            //---------------Test Result -----------------------
            Assert.IsNotNull(solution.DefaultAssembly, "A default assembly should always be created for the Solution");
            Assert.AreEqual(solutionName + ".BO", solution.DefaultAssembly.AssemblyName);
            Assert.AreSame(solution, solution.DefaultAssembly.Solution);
        }

        [Test]
        public void Test_CreateSolution_WithFileName_ShouldCreateStandardTypes()
        {
            //---------------Set up test pack-------------------
            SolutionCreator slnCreator = new SolutionCreator();
            string solutionName = TestUtilsShared.GetRandomString();
            string fileName = Path.Combine(Environment.CurrentDirectory, solutionName + ".fstart");
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            DMSolution solution = slnCreator.CreateSolution(fileName);
            //---------------Test Result -----------------------
            AssertPropertyTypesAreCreated(solution);
            AssertGridColumnControlTypesCreated(solution);
            AssertControlTypesCreated(solution);
            AssertFilterControlTypesCreated(solution);
        }

        [Test]
        public void Test_CreateSolution_WithFileName_ShouldCreateValidSolution()
        {
            //---------------Set up test pack-------------------
            SolutionCreator slnCreator = new SolutionCreator();
            string solutionName = TestUtilsShared.GetRandomString();
            string fileName = Path.Combine(Environment.CurrentDirectory, solutionName + ".fstart");
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            DMSolution solution = slnCreator.CreateSolution(fileName);
            //---------------Test Result -----------------------
            string message;
            Assert.IsTrue(solution.Status.IsValid(out message), message);
        }

        [Test]
        public void Test_GetGridControlType_ShouldReturnCorrectControlType()
        {
            //---------------Set up test pack-------------------
            SolutionCreator slnCreator = new SolutionCreator();
            DMSolution solution = slnCreator.CreateSolution();
            const string assemblyName = "System.Windows.Forms";
            const string controlType = "DataGridViewTextBoxColumn";
            UIGridColumnControlType foundPropertyType = solution.UIGridColumnControlTypes.Find(type => type.AssemblyName == assemblyName && type.TypeName == controlType);
            //---------------Assert Precondition----------------
            Assert.IsNotNull(foundPropertyType);
            //---------------Execute Test ----------------------
            UIGridColumnControlType gridColumnControlType = solution.GetGridColumnControlType(assemblyName, controlType);
            //---------------Test Result -----------------------
            Assert.IsNotNull(gridColumnControlType);
            Assert.AreSame(foundPropertyType, gridColumnControlType);
        }

        [Test]
        public void Test_GetBOEditorControlType_ShouldReturnCorrectControlType()
        {
            //---------------Set up test pack-------------------
            SolutionCreator slnCreator = new SolutionCreator();
            DMSolution solution = slnCreator.CreateSolution();
            const string assemblyName = "System.Windows.Forms";
            const string controlType = "TextBox";
            UIControlType foundPropertyType = solution.UIControlTypes.Find(type => type.AssemblyName == assemblyName && type.TypeName == controlType);
            //---------------Assert Precondition----------------
            Assert.IsNotNull(foundPropertyType);
            //---------------Execute Test ----------------------
            UIControlType uiControlType = solution.GetUIFormFieldControlType(assemblyName, controlType);
            //---------------Test Result -----------------------
            Assert.IsNotNull(uiControlType);
            Assert.AreSame(foundPropertyType, uiControlType);
        }

        [Test]
        public void Test_GetFilterControlType_ShouldReturnCorrectType()
        {
            //---------------Set up test pack-------------------
            SolutionCreator slnCreator = new SolutionCreator();
            DMSolution solution = slnCreator.CreateSolution();
            string assemblyName = BOBroker.GetMapperAssemblyName();
            const string controlType = "BoolCheckBoxFilter";
            UITypeDefinition foundPropertyType = solution.UIFilterControlTypes.Find(type => type.AssemblyName == assemblyName && type.TypeName == controlType);
            //---------------Assert Precondition----------------
            Assert.IsNotNull(foundPropertyType);
            //---------------Execute Test ----------------------
            UITypeDefinition uiControlType = solution.GetUIFilterControlType(assemblyName, controlType);
            //---------------Test Result -----------------------
            Assert.IsNotNull(uiControlType);
            Assert.AreSame(foundPropertyType, uiControlType);
        }

        [Test]
        public void Test_GetUIControlMapperType_ShouldReturnCorrectType()
        {
            //---------------Set up test pack-------------------
            SolutionCreator slnCreator = new SolutionCreator();
            DMSolution solution = slnCreator.CreateSolution();
            string assemblyName = BOBroker.GetMapperAssemblyName();
            const string controlType = "AutoLoadingRelationshipComboBoxMapper";
            UIControlMapperType foundControlMapperType = solution.UIControlMapperTypes.Find(type => type.AssemblyName == assemblyName && type.TypeName == controlType);

            //---------------Assert PreConditions---------------        
            Assert.IsNotNull(foundControlMapperType);
            //---------------Execute Test ----------------------
            UIControlMapperType controlMapperType = solution.GetUIControlMapperType(assemblyName, controlType);
            //---------------Test Result -----------------------
            Assert.IsNotNull(controlMapperType);
            Assert.AreSame(foundControlMapperType, controlMapperType);
            //---------------Tear Down -------------------------          
        }

        private static void AssertFilterControlTypesCreated(DMSolution solution)
        {
            BusinessObjectCollection<UITypeDefinition> types = solution.UIFilterControlTypes;
            Assert.AreEqual(5, types.Count, "By default all the standard UIGridColumnControlType should be created");
            AssertFilterControlTypeIsCreated(solution, BOBroker.GetMapperAssemblyName(), "BoolCheckBoxFilter");
            AssertFilterControlTypeIsCreated(solution, BOBroker.GetMapperAssemblyName(), "DateRangeComboBoxFilter");
            AssertFilterControlTypeIsCreated(solution, BOBroker.GetMapperAssemblyName(), "DateTimePickerFilter");
            AssertFilterControlTypeIsCreated(solution, BOBroker.GetMapperAssemblyName(), "StringComboBoxFilter");
            AssertFilterControlTypeIsCreated(solution, BOBroker.GetMapperAssemblyName(), "StringTextBoxFilter");
        }

        private static void AssertFilterControlTypeIsCreated(DMSolution solution, string assemblyName, string controlType)
        {
            string controlTypeFullName = "'" + assemblyName + "." + controlType + "'";
            UITypeDefinition uiControlType = solution.UIFilterControlTypes.Find(type => type.AssemblyName == assemblyName && type.TypeName == controlType);
            Assert.IsNotNull(uiControlType, "Control of type " + controlTypeFullName + " was not found for the solution");
            Assert.AreSame(solution, uiControlType.Solution, "the Control  " + controlTypeFullName + " type is not assigned to the correct solution");
        }

        private static void AssertGridColumnControlTypesCreated(DMSolution solution)
        {
            BusinessObjectCollection<UIGridColumnControlType> types = solution.UIGridColumnControlTypes;
            Assert.AreEqual(3, types.Count, "By default all the standard UIGridColumnControlType should be created");
            AssertGridColumnControlTypeIsCreated(solution, "System.Windows.Forms", "DataGridViewCheckBoxColumn");
            AssertGridColumnControlTypeIsCreated(solution, "System.Windows.Forms", "DataGridViewTextBoxColumn");
            AssertGridColumnControlTypeIsCreated(solution, "System.Windows.Forms", "DataGridViewComboBoxColumn");
        }

        private static void AssertControlTypesCreated(DMSolution solution)
        {
            BusinessObjectCollection<UIControlType> types = solution.UIControlTypes;
            Assert.AreEqual(4, types.Count, "By default all the standard UIControlType should be created");
            AssertGridControlTypeIsCreated(solution, "System.Windows.Forms", "CheckBox");
            AssertGridControlTypeIsCreated(solution, "System.Windows.Forms", "TextBox");
            AssertGridControlTypeIsCreated(solution, "System.Windows.Forms", "ComboBox");
            AssertGridControlTypeIsCreated(solution, "System.Windows.Forms", "DateTimePicker");
        }

        private static void AssertGridControlTypeIsCreated(DMSolution solution, string assemblyName, string controlType)
        {
            string controlTypeFullName = "'" + assemblyName + "." + controlType + "'";
            UIControlType uiControlType = solution.UIControlTypes.Find(type => type.AssemblyName == assemblyName && type.TypeName == controlType);
            Assert.IsNotNull(uiControlType, "Control of type " + controlTypeFullName + " was not found for the solution");
            Assert.AreSame(solution, uiControlType.Solution, "the Control  " + controlTypeFullName + " type is not assigned to the correct solution");
        }

        private static void AssertPropertyTypesAreCreated(DMSolution solution)
        {
            BusinessObjectCollection<DMPropertyType> types = solution.PropertyTypes;
            Assert.AreEqual(10, types.Count, "By default all the standard Property Types should be created");
            AssertPropertyTypeIsCreated(solution, "System", "String");
            AssertPropertyTypeIsCreated(solution, "System", "Int32");
            AssertPropertyTypeIsCreated(solution, "System", "Guid");
            AssertPropertyTypeIsCreated(solution, "System", "Single");
            AssertPropertyTypeIsCreated(solution, "System", "Boolean");
            AssertPropertyTypeIsCreated(solution, "System", "Decimal");
            AssertPropertyTypeIsCreated(solution, "System", "DateTime");
            AssertPropertyTypeIsCreated(solution, "System", "TimeSpan");
            AssertPropertyTypeIsCreated(solution, "System", "Double");
            AssertPropertyTypeIsCreated(solution, "System", "Int64");
        }

        private static void AssertGridColumnControlTypeIsCreated(DMSolution solution, string assemblyName, string controlType)
        {
            string controlTypeFullName = "'" + assemblyName +"." + controlType + "'";
            UIGridColumnControlType foundPropertyType = solution.UIGridColumnControlTypes.Find(type => type.AssemblyName == assemblyName && type.TypeName == controlType);
            Assert.IsNotNull(foundPropertyType, "Control of type " + controlTypeFullName + " was not found for the solution");
            Assert.AreSame(solution, foundPropertyType.Solution, "the Control  " + controlTypeFullName + " type is not assigned to the correct solution");
        }
        private static void AssertPropertyTypeIsCreated(DMSolution solution, string assemblyName, string controlType)
        {
            string controlTypeFullName = "'" + assemblyName +"." + controlType + "'";
            DMPropertyType foundPropertyType = solution.PropertyTypes.Find(type => type.AssemblyName == assemblyName && type.PropertyTypeName == controlType);
            Assert.IsNotNull(foundPropertyType, "Property of type " + controlTypeFullName + " was not found for the solution");
            Assert.AreSame(solution, foundPropertyType.Solution, "the property  " + controlTypeFullName + " type is not assigned to the correct solution");
        }
    }

}